package com.example.springboottest.example.httpclient.pool;

import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;

import java.io.IOException;

/**
 * UrlConnetcion 是jdk自带的对象
 * HTTPClient    是apache自带的
 * httpclient引入连接池
 *
 * 常见网络框架                                  特性
 * JDK’s  URLConnection                使用传统的线程阻塞 I/O
 * Apache HTTPClient                   使用基于线程池的线程阻塞 1/0
 * Apache AsyncHTTPClient              使用 NIO
 * Jersey                              它是 Rest 客户端／服务帮框架
 * OkHttp                              OKHttp 提供了对最新的 HTTP 协议版本 HTIP/2 SPDY 的支持，这使得对同一主机发出的所有请求都可以共享相同的套接字连接。
 * Netty                               Netty 是一个高性能、异步事件驱动的 NIO 框架，它提供了对 TCP/UDP 文件传输的支持。作为一个异步 NIO 框架，
 *                                     Netty的所有I/O操作都是异步非阻塞的 ，通过 Future-Listener 机制，用户可以方便地
 *                                     主动获取或者通过通知机制获得 I/O 操作结果
 */
public class TestHttpClientWithPool {
    /*全局连接池对象 */
    private static final PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();

    /**
     ＊静态代码块自己置连接池信息
     */
    static {
        //设置最大连接数
        connManager.setMaxTotal(200);
        //设置每个连接的路由数
        connManager.setDefaultMaxPerRoute(20);
    }

    /**
     * ＊获取 Http 客户端连接对象
     *
     * @param timeout 超时时间
     * @return Http 客户端连接对象
     */
    public static CloseableHttpClient getHttpClient(int timeout) {
        //创建 Http 请求配置参数
        RequestConfig requestConfig = RequestConfig.custom()
                //获取连接超时时间
                .setConnectionRequestTimeout(timeout)
                //请求超时时间
                .setConnectTimeout(timeout)
                //响应超时时间
                .setSocketTimeout(timeout)
                .build();

        //创建 HttpClient
        return HttpClients.custom()
                //把请求相关的超时信息设直到连接客户端
                .setDefaultRequestConfig(requestConfig)
                //把请求重试设直到连接客户端
                .setRetryHandler(new RetryHandler())
                //配直连接池管理对象
                .setConnectionManager(connManager)
                .build();
    }

    /**
     * Get 请求
     *
     * @param url     请求地址
     * @param timeout 超时时间
     * @return
     */
    public static String httpGet(String url, int timeout) {
        String msg = null;
        //获取客户端连接对象
        CloseableHttpClient httpClient = getHttpClient(timeout);
        //创建 Get 请求对象
        HttpGet httpGet = new HttpGet(url);
        CloseableHttpResponse response = null;
        try {
            //执行请求
            response = httpClient.execute(httpGet);
            //获取响应实体
            HttpEntity entity = response.getEntity();
            //获取响应信息
            msg = EntityUtils.toString(entity, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (response != null) {
                try {
                    EntityUtils.consume(response.getEntity());
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return msg;
    }

    public static void main(String[] args) {
        System.out.println(httpGet("http://www.163.com", 6000));
    }
}